using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Net.Browser;
using System.Reflection;
using System.Windows;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Navigation;
using Lib.Approval;
using Lib.Helper;
using Lib.Mail;
using MSIACCSL2.ApplicationStateServices;
using MSIACCSL2.Command;
using MSIACCSL2.CostCenterServices;
using MSIACCSL2.CurrencyServices;
using MSIACCSL2.CustomerServices;
using MSIACCSL2.DeliveryTypeServices;
using MSIACCSL2.InventoryServices;
using MSIACCSL2.ItemServices;
using MSIACCSL2.PalletServices;
using MSIACCSL2.PreSalesOrderServices;
using MSIACCSL2.SalesmanServices;
using MSIACCSL2.SalesOrderServices;
using MSIACCSL2.SubGroupServices;
using MSIACCSL2.Views.SalesOrder;
using MSIACCSL2.WarehouseServices;
using WcfService1.DTO;
using DeleteDetailCompletedEventArgs = MSIACCSL2.SalesOrderServices.DeleteDetailCompletedEventArgs;
using GetListByCriteriaCompletedEventArgs = MSIACCSL2.SalesOrderServices.GetListByCriteriaCompletedEventArgs;
using GetListCompletedEventArgs = MSIACCSL2.SalesOrderServices.GetListCompletedEventArgs;
using SaveCompletedEventArgs = MSIACCSL2.SalesOrderServices.SaveCompletedEventArgs;


namespace MSIACCSL2.ViewModels
{
    public class SalesOrderViewModel : ViewModelBase
    {
        #region Delegates

        public delegate void Completed(Object param);

        #endregion

        private static string OrderType;
        private static string PropertySort;
        public static Mode mode;
        public static Completed OnSearchCompleted;
        private static NavigationService _NavigationService;
        private static Search frmSearch;
        private readonly AplicationStateServicesClient ApplicationService;
        private readonly CostCenterServicesClient CostCenterClient;


        private readonly CurrencyServicesClient CurrencyClient;
        private readonly CustomerServicesClient CustomerClient;
        private readonly DeliveryTypeServicesClient DeliveryTypeClient;
        private readonly ItemServicesClient ItemClient;
        private readonly PreSalesOrderServicesClient PreSalesClient;
        private readonly SalesmanServicesClient SalesmanClient;
        private readonly SubGroupServiceClient SubgroupClient;
        private readonly WarehouseServicesClient WarehouseClient;
        private readonly SalesOrderServicesClient client;
        private int CurrentPage;
        public string Expression;
        private InventoryServiceClient InventoryClient;
        private bool IsUsed;
        private ObservableCollection<int> Pages;
        private PalletServicesClient PalletClient;
        private ObservableCollection<CostCenterDTO> _CostCenters;
        private ObservableCollection<CurrencyDTO> _Currencys;
        private ObservableCollection<CustomerDTO> _Customers;
        private ObservableCollection<DeliveryTypeDTO> _DeliveryTypes;
        private Visibility _GridInventoryVisibility;
        private Visibility _GridItemVisibility;
        private Visibility _GridSubgroupVisibility;
        private bool _IsBusy;
        private bool _IsEnabled;
        private ObservableCollection<ItemDTO> _Items;
        private ObservableCollection<PreSalesOrderDTO> _PreSalesOrders;
        private SalesOrderDTO _SalesOrder;
        private SalesOrderDetailDTO _SalesOrderDetailCurrent;
        private PagedCollectionView _SalesOrders;
        private ObservableCollection<EmployeeDTO> _Salesmans;
        private List<string> _errors;
        private InventoryDTO _inventory;
        private ObservableCollection<ItemDTO> _items;
        private Visibility _messageVisibility;
        private PagedCollectionView _pageSources;
        private ObservableCollection<PalletDTO> _pallets;
        private ObservableCollection<SubGroupDTO> _subgroups;
        private ObservableCollection<WarehouseDTO> _warehouses;
        private Dictionary<string, object> criteria;
        private string expression;
        private bool _IsItem;
        private bool _IsSubgroup;
        private bool _IsSerialNumber;

        public SalesOrderViewModel()
        {
            IsEnabled = true;

            if (!DesignerProperties.IsInDesignTool)
            {
                client = new SalesOrderServicesClient();
                CurrencyClient = new CurrencyServicesClient();
                CustomerClient = new CustomerServicesClient();
                DeliveryTypeClient = new DeliveryTypeServicesClient();
                PreSalesClient = new PreSalesOrderServicesClient();
                SubgroupClient = new SubGroupServiceClient();
                ItemClient = new ItemServicesClient();
                InventoryClient = new InventoryServiceClient();
                WarehouseClient = new WarehouseServicesClient();
                PalletClient = new PalletServicesClient();
                CostCenterClient = new CostCenterServicesClient();
                SalesmanClient = new SalesmanServicesClient();
                ApplicationService = new AplicationStateServicesClient();

                OnPageChanged = new DelegateCommand(PageIndexChanged, CanPageIndexChanged);
                Save = new DelegateCommand(SaveSalesOrder, CanSave);
                New = new DelegateCommand(NewSalesOrder, CanNew);
                Unload = new DelegateCommand(Release, CanUnload);
                SearchCommand = new DelegateCommand(SearchSalesOrder, CanSearch);
                SearchResultCommand = new DelegateCommand(SearchResult, CanSearchResult);
                CancelCommand = new DelegateCommand(Cancel, CanCancelCommand);
                GetRateCommand = new DelegateCommand(GetRate, CanGetRateCommand);
                LoadPreSalesCommand = new DelegateCommand(LoadPreSales, CanLoadPreSalesCommand);
                SubGroupCommand = new DelegateCommand(EntrySubGroup, CanSubgroupCommand);
                ItemCommand = new DelegateCommand(EntryItem, CanItemCommand);
                InventoryCommand = new DelegateCommand(EntryInventory, CanInventoryCommand);
                GetSubGroupCommand = new DelegateCommand(GetSubgroupByName, CanGetSubgroupCommand);


                MessageVisibility = Visibility.Collapsed;
                GridSubgroupVisibility = Visibility.Collapsed;
                GridItemVisibility = Visibility.Collapsed;
                GridInventoryVisibility = Visibility.Collapsed;

                if (mode == Mode.Edit)
                {
                    PrepareEdit();
                }
                else if (mode == Mode.Search)
                {
                    SalesOrder = new SalesOrderDTO();
                    SalesOrder.SODate = null;
                    GetCurrencyList();
                    GetDeliveryTypeList();
                }
                else if (mode == Mode.Add)
                {
                    PrepareAdd();
                }
                else
                {
                    GetList(1, null);
                }
            }
        }


        public ObservableCollection<CostCenterDTO> CostCenters
        {
            get { return _CostCenters; }
            private set
            {
                if (CostCenters == value) return;
                _CostCenters = value;
                FirePropertyChanged("CostCenters");
            }
        }

        public PagedCollectionView SalesOrders
        {
            get { return _SalesOrders; }

            private set
            {
                if (SalesOrders == value) return;
                _SalesOrders = value;
                int i = (CurrentPage*30);
                foreach (object SalesOrder in SalesOrders)
                {
                    i += 1;

                    ((SalesOrderDTO) SalesOrder).No = i;
                }
                FirePropertyChanged("SalesOrders");
                SalesOrders.CollectionChanged += SalesOrder_CollectionChanged;
            }
        }

        public PagedCollectionView PageSources
        {
            get { return _pageSources; }
            private set
            {
                if (PageSources == value) return;
                _pageSources = value;
                FirePropertyChanged("PageSources");
            }
        }


        public ObservableCollection<CurrencyDTO> Currencys
        {
            get { return _Currencys; }
            private set
            {
                if (Currencys == value) return;
                _Currencys = value;
                FirePropertyChanged("Currencys");
            }
        }


        public ObservableCollection<CustomerDTO> Customers
        {
            get { return _Customers; }
            private set
            {
                if (Customers == value) return;
                _Customers = value;
                FirePropertyChanged("Customers");
            }
        }

        public ObservableCollection<EmployeeDTO> Salesmans
        {
            get { return _Salesmans; }
            private set
            {
                if (Salesmans == value) return;
                _Salesmans = value;
                FirePropertyChanged("Salesmans");
            }
        }


        public ObservableCollection<DeliveryTypeDTO> DeliveryTypes
        {
            get { return _DeliveryTypes; }
            private set
            {
                if (DeliveryTypes == value) return;
                _DeliveryTypes = value;
                FirePropertyChanged("DeliveryTypes");
            }
        }

        public ObservableCollection<PreSalesOrderDTO> PreSalesOrders
        {
            get { return _PreSalesOrders; }
            private set
            {
                if (PreSalesOrders == value) return;
                _PreSalesOrders = value;
                FirePropertyChanged("PreSalesOrders");
            }
        }


        public bool IsBusy
        {
            get { return _IsBusy; }
            internal set
            {
                _IsBusy = value;
                FirePropertyChanged("IsBusy");
            }
        }


        public bool IsEnabled
        {
            get { return _IsEnabled; }
            internal set
            {
                _IsEnabled = value;
                FirePropertyChanged("IsEnabled");
            }
        }


        public bool IsSerialNumber
        {
            get { return _IsSerialNumber; }
            internal set
            {
                _IsSerialNumber = value;
                FirePropertyChanged("IsSerialNumber");
            }
        }

        public bool IsSubgroup
        {
            get { return _IsSubgroup; }
            internal set
            {
                _IsSubgroup = value;
                FirePropertyChanged("IsSubgroup");
            }
        }

        public bool IsItem
        {
            get { return _IsItem; }
            internal set
            {
                _IsItem = value;
                FirePropertyChanged("IsItem");
            }
        }

        public long RecordCount { get; set; }

        //Buat binding ke child form waktu mau edit
        public SalesOrderDTO SalesOrder
        {
            get { return _SalesOrder; }
            private set
            {
                if (SalesOrder == value) return;
                _SalesOrder = value;
                FirePropertyChanged("SalesOrder");
            }
        }


        public ICommand OnPageChanged { get; set; }
        public ICommand Save { get; set; }
        public ICommand New { get; set; }
        public ICommand Edit { get; set; }
        public ICommand Unload { get; set; }
        public ICommand SearchCommand { get; set; }
        public ICommand SearchResultCommand { get; set; }
        public ICommand CancelCommand { get; set; }

        public List<string> Errors
        {
            get { return _errors; }
            private set
            {
                if (Errors == value) return;
                _errors = value;
                FirePropertyChanged("Errors");
            }
        }

        public Visibility MessageVisibility
        {
            get { return _messageVisibility; }
            private set
            {
                if (MessageVisibility == value) return;
                _messageVisibility = value;
                FirePropertyChanged("MessageVisibility");
            }
        }

        public Visibility GridItemVisibility
        {
            get { return _GridItemVisibility; }
            private set
            {
                if (GridItemVisibility == value) return;
                _GridItemVisibility = value;
                FirePropertyChanged("GridItemVisibility");
            }
        }

        public Visibility GridSubgroupVisibility
        {
            get { return _GridSubgroupVisibility; }
            private set
            {
                if (GridSubgroupVisibility == value) return;
                _GridSubgroupVisibility = value;
                FirePropertyChanged("GridSubgroupVisibility");
            }
        }

        public Visibility GridInventoryVisibility
        {
            get { return _GridInventoryVisibility; }
            private set
            {
                if (GridInventoryVisibility == value) return;
                _GridInventoryVisibility = value;
                FirePropertyChanged("GridInventoryVisibility");
            }
        }

        public ObservableCollection<SubGroupDTO> Subgroups
        {
            get { return _subgroups; }
            private set
            {
                if (Subgroups == value) return;
                _subgroups = value;
                FirePropertyChanged("Subgroups");
            }
        }

        public ObservableCollection<WarehouseDTO> Warehouses
        {
            get { return _warehouses; }
            private set
            {
                if (Warehouses == value) return;
                _warehouses = value;
                FirePropertyChanged("Warehouses");
            }
        }

        public ObservableCollection<PalletDTO> Pallets
        {
            get { return _pallets; }
            private set
            {
                if (Pallets == value) return;
                _pallets = value;
                FirePropertyChanged("Pallets");
            }
        }

        public SalesOrderDetailDTO SalesOrderDetailCurrent
        {
            get { return _SalesOrderDetailCurrent; }
            private set
            {
                if (SalesOrderDetailCurrent == value) return;
                _SalesOrderDetailCurrent = value;
                FirePropertyChanged("SalesOrderDetailCurrent");
            }
        }

        public ObservableCollection<ItemDTO> Items
        {
            get { return _Items; }
            set
            {
                if (Items == value) return;
                _Items = value;
                FirePropertyChanged("Items");
            }
        }

        public ICommand GetRateCommand { get; set; }
        public ICommand LoadPreSalesCommand { get; set; }
        public ICommand GetSubGroupCommand { get; set; }
        public ICommand SubGroupCommand { get; set; }
        public ICommand ItemCommand { get; set; }
        public ICommand InventoryCommand { get; set; }

        private void PrepareEdit()
        {
            SalesOrder = (SalesOrderDTO) Navigation.Args;
            GetSalesOrder(SalesOrder);
            CekTransaksi();
        }

        private void PrepareAdd()
        {
            GetCurrencyList();
            GetDeliveryTypeList();
            //GetPreSalesList();
            GetCostCenterList();
            GetSalesmanList(Mode.Add);
            GetWarehouseList(Mode.Add);

            SalesOrder = new SalesOrderDTO();
            SalesOrder.SalesOrderDetails = new ObservableCollection<SalesOrderDetailDTO>();
            var SalesOrderDetail = new SalesOrderDetailDTO();
            SalesOrder.SalesOrderDetails.Add(SalesOrderDetail);
            SalesOrderDetail.DiscountType = "%";

            GridInventoryVisibility = Visibility.Collapsed;
            GridItemVisibility = Visibility.Collapsed;
            GridSubgroupVisibility = Visibility.Collapsed;

            IsSerialNumber = true;
            EntryInventory(SalesOrder);

            //CekTransaksi();
        }


        public void CekTransaksi()
        {
            ApplicationService.IsTransactionUsedCompleted += ApplicationService_IsTransactionUsedCompleted;
            if (string.IsNullOrEmpty(SalesOrder.SONo))
            {
                ApplicationService.IsTransactionUsedAsync(SalesOrder.ToString(), GlobalVar.User, mode);
                GlobalVar.CurrentTransaction = SalesOrder.ToString();
            }
            else
            {
                ApplicationService.IsTransactionUsedAsync(SalesOrder.SONo, GlobalVar.User, mode);
                GlobalVar.CurrentTransaction = SalesOrder.SONo;
            }
        }

        private void ApplicationService_IsTransactionUsedCompleted(object sender, IsTransactionUsedCompletedEventArgs e)
        {
            ApplicationService.IsTransactionUsedCompleted -= ApplicationService_IsTransactionUsedCompleted;
            IsUsed = e.Result;
            mode = (Mode) e.UserState;
            if (IsUsed)
            {
                MessageBox.Show("Transaksi sedang digunakan!");
                if (mode == Mode.Add) //If Add Mode
                {
                    mode = Mode.Idle;
                    Navigation.MyNavigation.Navigate(new Uri("/SalesOrder/Index", UriKind.Relative));
                }
                else //Edit Mode just view Only
                {
                    IsEnabled = false;
                }
            }
        }


        private void GetSalesOrder(SalesOrderDTO salesOrderDto)
        {
            IsBusy = true;
            client.GetSalesOrderCompleted += client_GetSalesOrderCompleted;
            client.GetSalesOrderAsync(salesOrderDto.SONo);
        }

        private void client_GetSalesOrderCompleted(object sender, GetSalesOrderCompletedEventArgs e)
        {
            client.GetSalesOrderCompleted -= client_GetSalesOrderCompleted;
            SalesOrder = e.Result;
            if (SalesOrder.Status == Status.Void || SalesOrder.Status == Status.Close) IsEnabled = false;
            if (SalesOrder.SalesOrderDetails == null)
                SalesOrder.SalesOrderDetails = new ObservableCollection<SalesOrderDetailDTO>();
            if (SalesOrder.SalesOrderDetails.Count == 0)
                SalesOrder.SalesOrderDetails.Add(new SalesOrderDetailDTO());

            if (SalesOrder.Type != null)
                if (SalesOrder.Type.ToLower() == "subgroup")
                {
                    GetSubGroupList(Mode.Edit);
                    GridSubgroupVisibility = Visibility.Visible;
                    IsSubgroup = true;
                }
                else if (SalesOrder.Type.ToLower() == "item")
                {
                    GetItemList(Mode.Edit);
                    GridItemVisibility = Visibility.Visible;
                    IsItem = true;
                }
                else
                {
                    GridInventoryVisibility = Visibility.Visible;
                    IsSerialNumber = true;
                }

            mode = Mode.Edit;
            GetCurrencyList();
            GetDeliveryTypeList();
            GetPreSalesList();
            GetCostCenterList();
            GetSalesmanList(Mode.Edit);
            GetWarehouseList(Mode.Edit);
            IsBusy = false;
        }

        private void GetWarehouseList(Mode mode)
        {
            WarehouseClient.GetAllWarehouseCompleted += WarehouseClient_GetAllWarehouseCompleted;
            WarehouseClient.GetAllWarehouseAsync(mode);
        }

        private void WarehouseClient_GetAllWarehouseCompleted(object sender, GetAllWarehouseCompletedEventArgs e)
        {
            WarehouseClient.GetAllWarehouseCompleted -= WarehouseClient_GetAllWarehouseCompleted;
            Warehouses = e.Result;
            var mode = (Mode) e.UserState;
            if (mode == Mode.Edit)
            {
                if (SalesOrder.Warehouse != null)
                    SalesOrder.Warehouse =
                        Warehouses.FirstOrDefault(x => x.KodeWarehouse == SalesOrder.Warehouse.KodeWarehouse);
            }
        }


        public void GetSalesmanList(Mode mode)
        {
            SalesmanClient.GetAllSalesmanCompleted += SalesmanClient_GetAllSalesmanCompleted;
            SalesmanClient.GetAllSalesmanAsync(mode);
        }

        private void SalesmanClient_GetAllSalesmanCompleted(object sender, GetAllSalesmanCompletedEventArgs e)
        {
            SalesmanClient.GetAllSalesmanCompleted -= SalesmanClient_GetAllSalesmanCompleted;
            Salesmans = e.Result;
            var mode = (Mode) e.UserState;
            if (mode == Mode.Edit)
            {
                if (SalesOrder.Salesman != null)
                    SalesOrder.Salesman =
                        Salesmans.FirstOrDefault(x => x.KodeSalesman == SalesOrder.Salesman.KodeSalesman);
            }
        }

        private void GetCostCenterList()
        {
            CostCenterClient.GetAllCostCenterCompleted += CostCenterClient_GetAllCostCenterCompleted;
            CostCenterClient.GetAllCostCenterAsync();
        }

        private void CostCenterClient_GetAllCostCenterCompleted(object sender, GetAllCostCenterCompletedEventArgs e)
        {
            CostCenterClient.GetAllCostCenterCompleted -= CostCenterClient_GetAllCostCenterCompleted;
            CostCenters = e.Result;
            if (SalesOrder != null)
                if (SalesOrder.CostCenter != null)
                    SalesOrder.CostCenter =
                        CostCenters.FirstOrDefault(x => x.CostCenterId == SalesOrder.CostCenter.CostCenterId);
        }


        public void Complete(Object param)
        {
            OnSearchCompleted(param);
        }

        private void SalesOrder_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (((PagedCollectionView) sender).SortDescriptions.Count > 0)
            {
                if (((PagedCollectionView) sender).SortDescriptions[0].PropertyName.ToLower() == "no") return;

                PropertySort = ((PagedCollectionView) sender).SortDescriptions[0].PropertyName;
                if (string.IsNullOrEmpty(OrderType))
                {
                    OrderType = "ASC";
                }
                else
                {
                    OrderType = OrderType == "ASC" ? OrderType = "DESC" : OrderType = "ASC";
                }
                GetList(1, PropertySort);
            }
        }


        public void SaveSalesOrder(Object salesOrder)
        {
            //SalesOrder = (SalesOrderDTO) salesOrder;
            if (SalesOrder.SalesOrderDetails.Count == 1)
            {
                //Bila tidak ada yang dipilih di detail maka details harus dihapus
                if (SalesOrder.SalesOrderDetails[0].SubGroup == null &&
                    SalesOrder.SalesOrderDetails[0].Item == null &&
                    SalesOrder.SalesOrderDetails[0].Inventory == null)
                    SalesOrder.SalesOrderDetails.Clear();
            }
            Validate();
            if (Errors.Count > 0) return;
            SalesOrder.created_by = GlobalVar.User.UserID;
            SalesOrder.modified_by = GlobalVar.User.UserID;
            IsBusy = true;
            client.SaveCompleted += client_SaveCompleted;
            client.SaveAsync(SalesOrder, mode);
        }

        private void client_SaveCompleted(object sender, SaveCompletedEventArgs e)
        {
            if (e.Error != null) Validate(e.Error.ToString());
            client.SaveCompleted -= client_SaveCompleted;
            mode = (Mode) e.UserState;
            if (e.Result)
            {
                IsBusy = false;
                ClearTransaksi(mode);
                mode = Mode.Idle;
                Navigation.MyNavigation.Navigate(new Uri("/SalesOrder/Index", UriKind.Relative));
            }
            else
            {
                IsBusy = false;
                MessageBox.Show("Simpan Gagal, Periksa data Anda!");
            }
        }

        private void ClearTransaksi(Mode mode)
        {
            ApplicationService.ClearTransactionCompleted += ApplicationService_ClearTransactionCompleted;
            if (mode == Mode.Add)
                ApplicationService.ClearTransactionAsync(SalesOrder.ToString(), GlobalVar.User);
            else
                ApplicationService.ClearTransactionAsync(SalesOrder.SONo, GlobalVar.User);
        }

        private void ApplicationService_ClearTransactionCompleted(object sender, AsyncCompletedEventArgs e)
        {
            ApplicationService.ClearTransactionCompleted -= ApplicationService_ClearTransactionCompleted;
        }


        public void GetList(int? page, string sortProp)
        {
            IsBusy = true;
            client.GetListCompleted += client_GetListCompleted;
            client.GetListAsync(page ?? 1, sortProp, OrderType);
        }

        private void client_GetListCompleted(object sender, GetListCompletedEventArgs e)
        {
            RecordCount = e.recordCount;
            if (PageSources == null) CreatePageNumber();
            client.GetListCompleted -= client_GetListCompleted;
            SalesOrders = new PagedCollectionView(e.Result);
            IsBusy = false;
            Complete(this);
        }


        private void NewSalesOrder(Object param)
        {
            mode = Mode.Add;
            Navigation.MyNavigation = (NavigationService) param;
            Navigation.MyNavigation.Navigate(new Uri("/SalesOrder/frmAdd", UriKind.Relative));
        }


        private void SearchSalesOrder(Object param)
        {
            mode = Mode.Search;
            frmSearch = new Search();
            frmSearch.Show();
        }


        private void SearchResult(Object param)
        {
            criteria = new Dictionary<string, object>();

            foreach (PropertyInfo prop in SalesOrder.GetType().GetProperties())
            {
                if (prop.PropertyType == typeof (Decimal))
                {
                    if ((Decimal) prop.GetValue(SalesOrder, null) == 0) continue;
                }
                if (prop.PropertyType == typeof (Int32))
                {
                    if ((Int32) prop.GetValue(SalesOrder, null) == 0) continue;
                }
                if (prop.PropertyType == typeof (Int64))
                {
                    if ((Int64) prop.GetValue(SalesOrder, null) == 0) continue;
                }
                if (prop.PropertyType == typeof (Double))
                {
                    if ((Double) prop.GetValue(SalesOrder, null) == 0) continue;
                }
                if (prop.PropertyType == typeof (String))
                {
                    if (String.IsNullOrEmpty((String) prop.GetValue(SalesOrder, null))) continue;
                }
                if (prop.PropertyType == typeof (DateTime))
                {
                    if (prop.GetValue(SalesOrder, null).ToString().Contains("0001")) continue;
                }
                if (prop.GetValue(SalesOrder, null) == null) continue;
                if (prop.PropertyType.Name == "No") continue;

                if (prop.PropertyType.Name.ToLower().Contains("dto"))
                {
                    foreach (PropertyInfo propertyInfo in prop.GetValue(SalesOrder, null).GetType().GetProperties()
                        )
                    {
                        if (propertyInfo.Name.ToLower().Contains("id") || propertyInfo.Name.ToLower().Contains("kode") ||
                            propertyInfo.Name.ToLower().Contains("serial") ||
                            propertyInfo.Name.ToLower().Contains("code"))
                        {
                            criteria.Add(prop.Name, propertyInfo.GetValue(prop.GetValue(SalesOrder, null), null));
                            break;
                        }
                    }
                }
                else
                {
                    criteria.Add(prop.Name, prop.GetValue(SalesOrder, null));
                }
            }

             expression = string.Empty;
            if (frmSearch.rblOr.IsChecked ?? false) expression = "OR";
            else expression = "AND";
            SalesOrderSearch(criteria, expression,1);
        }

        private void SalesOrderSearch(Dictionary<String, Object> criteria, string expression,int page)
        {
            if (criteria.ContainsKey("Status")) criteria.Remove("Status");
            frmSearch.DialogResult = true;
            IsBusy = true;
            Complete(this);
            client.GetListByCriteriaCompleted += client_GetListByCriteriaCompleted;
            client.GetListByCriteriaAsync(criteria, expression, page);
        }

        private void client_GetListByCriteriaCompleted(object sender, GetListByCriteriaCompletedEventArgs e)
        {
            client.GetListByCriteriaCompleted -= client_GetListByCriteriaCompleted;
            SalesOrders = new PagedCollectionView(e.Result);
            if (RecordCount != e.recordCount)
            {
                RecordCount = e.recordCount;
                CreatePageNumber();
            }
            IsBusy = false;
        }


        private void GetCurrencyList()
        {
            CurrencyClient.GetAllCurrencyCompleted += CurrencyClient_GetAllCurrencyCompleted;
            CurrencyClient.GetAllCurrencyAsync();
        }

        private void CurrencyClient_GetAllCurrencyCompleted(object sender, GetAllCurrencyCompletedEventArgs e)
        {
            CurrencyClient.GetAllCurrencyCompleted -= CurrencyClient_GetAllCurrencyCompleted;
            Currencys = e.Result;

            if (SalesOrder != null)
            {
                SalesOrder.Currency = Currencys.FirstOrDefault(c => c.CurrencyCode == "Rp");
                if (SalesOrder.Currency == null) return;
                SalesOrder.Currency =
                    Currencys.FirstOrDefault(s => s.CurrencyCode == SalesOrder.Currency.CurrencyCode);
            }
        }

        private void GetDeliveryTypeList()
        {
            DeliveryTypeClient.GetAllDeliveryTypeCompleted += DeliveryTypeClient_GetAllDeliveryTypeCompleted;
            DeliveryTypeClient.GetAllDeliveryTypeAsync();
        }

        private void DeliveryTypeClient_GetAllDeliveryTypeCompleted(object sender,
                                                                    GetAllDeliveryTypeCompletedEventArgs e)
        {
            DeliveryTypeClient.GetAllDeliveryTypeCompleted -= DeliveryTypeClient_GetAllDeliveryTypeCompleted;
            DeliveryTypes = e.Result;

            if (SalesOrder != null)
            {
                if (SalesOrder.DeliveryType == null) return;
                SalesOrder.DeliveryType =
                    DeliveryTypes.FirstOrDefault(s => s.DeliveryCode == SalesOrder.DeliveryType.DeliveryCode);
            }
        }

        public void GetPreSalesList()
        {
            PreSalesClient.GetAllPreSalesOrderCompleted += PreSalesClient_GetAllPreSalesOrderCompleted;
            PreSalesClient.GetAllPreSalesOrderAsync();
        }

        private void PreSalesClient_GetAllPreSalesOrderCompleted(object sender, GetAllPreSalesOrderCompletedEventArgs e)
        {
            PreSalesClient.GetAllPreSalesOrderCompleted -= PreSalesClient_GetAllPreSalesOrderCompleted;
            //Tambah item kosong buat pilihan
            e.Result.Insert(0, new PreSalesOrderDTO {PSNo = "--Pilih--"});
            
            //Edit Mode
            if (SalesOrder != null)
            {
                PreSalesOrders = new ObservableCollection<PreSalesOrderDTO>(e.Result.Where(x => x.SRDate <= SalesOrder.SODate));
                if (SalesOrder.PreSalesOrder == null) return;
                if (! PreSalesOrders.Any(x=>x.PSNo==SalesOrder.PreSalesOrder.PSNo))
                    PreSalesOrders.Add(SalesOrder.PreSalesOrder);
                SalesOrder.RaisePropertyChanged("PreSalesOrder");
            }
        }


        private void CreatePageNumber()
        {
            Pages = new ObservableCollection<int>();
            for (int i = 0; i < RecordCount; i++)
            {
                Pages.Add(i);
            }
            PageSources = new PagedCollectionView(Pages);
        }


        private void PageIndexChanged(Object pageIndex)
        {
            //Jika Pertama kali jangan di Getlagi
            SalesOrder = null;
            if (SalesOrders != null && CurrentPage != (int) pageIndex)
            {
                CurrentPage = (int) pageIndex;
                if (mode == Mode.Search)
                    SalesOrderSearch(criteria, expression, (int)pageIndex + 1);
                else if (String.IsNullOrEmpty(PropertySort))
                    GetList((int) pageIndex + 1, null);
                else GetList((int) pageIndex + 1, PropertySort);
            }
        }


        public bool CanPageIndexChanged(Object param)
        {
            return true;
        }

        public bool CanSave(Object param)
        {
            return true;
        }

        public bool CanNew(Object param)
        {
            return true;
        }

        public bool CanEdit(Object param)
        {
            return true;
        }

        public bool CanUnload(Object param)
        {
            return true;
        }

        public bool CanSearch(Object param)
        {
            return true;
        }

        public bool CanSearchResult(Object param)
        {
            return true;
        }

        public bool CanCancelCommand(Object param)
        {
            return true;
        }

        public bool CanGetSubgroupCommand(Object param)
        {
            return true;
        }

        public void Release(Object param)
        {
            param = null;
            SalesOrder = null;
            OrderType = null;
            PropertySort = null;
            mode = Mode.Idle;
        }


        public void Refresh()
        {
            if (SalesOrders == null)
                GetList(1, null);
            else
                Complete(this);
        }


        public void Validate(string error = null)
        {
            Errors = new List<string>();
            //if (string.IsNullOrEmpty(SalesOrder.SONo))
            //    Errors.Add("Nomor SO tidak boleh kosong");
            if (SalesOrder.Salesman == null)
                Errors.Add("Salesman tidak boleh kosong!");
            if (SalesOrder.CostCenter == null)
                Errors.Add("CostCenter tidak boleh kosong!");
            if (SalesOrder.Currency == null)
                Errors.Add("Currency tidak boleh kosong!");
            if (SalesOrder.Warehouse == null)
                Errors.Add("Warehouse tidak boleh kosong!");
            if (SalesOrder.Type == null)
                Errors.Add(" Sales Order Type tidak boleh kosong!");
            if (SalesOrder.SalesOrderDetails.Count < 1)


                //validasiDetail

                if (SalesOrder.Type == null)
                    Errors.Add("SalesOrder Type harus dipilih!");

               if (SalesOrder.Type != null)
               {
                   if (SalesOrder.Type.ToLower() == "subgroup")
                   {
                       for (int i = 0; i <= SalesOrder.SalesOrderDetails.Count - 1; i++)
                       {
                           if (SalesOrder.SalesOrderDetails[i].SubGroup == null ||
                               string.IsNullOrEmpty(SalesOrder.SalesOrderDetails[i].SubGroup.SubGroupID))
                               SalesOrder.SalesOrderDetails.RemoveAt(i);
                       }
                   }
                   else if (SalesOrder.Type.ToLower() == "item")
                   {
                       for (int i = 0; i <= SalesOrder.SalesOrderDetails.Count - 1; i++)
                       {
                           if (SalesOrder.SalesOrderDetails[i].Item == null ||
                               string.IsNullOrEmpty(SalesOrder.SalesOrderDetails[i].Item.ItemId))
                               SalesOrder.SalesOrderDetails.RemoveAt(i);
                       }
                   }
                   else
                   {
                       var count = SalesOrder.SalesOrderDetails.Count - 1;
                       for (int i = 0; i <= count; i++)
                       {
                           if (SalesOrder.SalesOrderDetails[i].Inventory == null ||
                               string.IsNullOrEmpty(SalesOrder.SalesOrderDetails[i].Inventory.SerialNumber))
                               SalesOrder.SalesOrderDetails.RemoveAt(i);
                       }
                   }
               }
                    

            if (!string.IsNullOrEmpty(error))
                Errors.Add(error);

            if (Errors.Count > 0)
                MessageVisibility = Visibility.Visible;
            else
                MessageVisibility = Visibility.Collapsed;
        }

        public void Cancel(Object param)
        {
            MessageBoxResult res = MessageBox.Show("Are You Sure Want to Cancel ?", "Confirmation",
                                                   MessageBoxButton.OKCancel);
            if (res == MessageBoxResult.OK)
            {
                if (!IsUsed) ClearTransaksi(mode);
                mode = Mode.Idle;
                Navigation.MyNavigation.GoBack();
            }
        }

        public void GetLastNoSalesOrder(Object param)
        {
            if (param == null) return;
            client.GetLastSONoCompleted += client_GetLastSONoCompleted;
            client.GetLastSONoAsync(param as CostCenterDTO, "SO", (param as CostCenterDTO).CostCenterId);
        }

        private void client_GetLastSONoCompleted(object sender, GetLastSONoCompletedEventArgs e)
        {
            client.GetLastSONoCompleted -= client_GetLastSONoCompleted;
            string res = e.Result;
            string formatSO = "0000";
            string kodeSO = string.Empty;

            if (e.Result.Length <= 4)
            {
                res = formatSO;
                kodeSO = e.Result;
            }
            else
            {
                res = e.Result.Split(new[] {"/"}, StringSplitOptions.RemoveEmptyEntries)[3];
                kodeSO = e.Result.Split(new[] {"/"}, StringSplitOptions.RemoveEmptyEntries)[0];
            }

            string soNum = formatSO.Substring(0, formatSO.Length - (int.Parse(res) + 1).ToString().Length) +
                           (int.Parse(res) + 1);
            string costCenter = e.UserState.ToString();
            SalesOrder.SONo = kodeSO + "/" + costCenter + "/" + DateTime.Now.Year + "/" + soNum;
        }


        public bool CanGetRateCommand(Object param)
        {
            return true;
        }

        public void GetRate(Object param)
        {
            if (SalesOrder == null) return;
            CurrencyClient.GetCurrencyCompleted += CurrencyClient_GetCurrencyCompleted;
            CurrencyClient.GetCurrencyAsync(SalesOrder.Currency.CurrencyCode);
        }

        private void CurrencyClient_GetCurrencyCompleted(object sender, GetCurrencyCompletedEventArgs e)
        {
            CurrencyClient.GetCurrencyCompleted -= CurrencyClient_GetCurrencyCompleted;
            if (SalesOrder != null) SalesOrder.Rate = e.Result.Kurs;
        }

        public bool CanLoadPreSalesCommand(Object param)
        {
            return true;
        }

        private void LoadPreSales(Object param)
        {
            if (SalesOrder.Type == null)
            {
                MessageBox.Show("Pilih dulu Tipenya!");
                return;
            }
            var Presales = (PreSalesOrderDTO) param;
            if (param == null || Presales.PSNo.ToLower().Contains("pilih")) return;
            PreSalesClient.GetPreSalesOrderCompleted += PreSalesClient_GetPreSalesOrderCompleted;
            PreSalesClient.GetPreSalesOrderAsync(SalesOrder.PreSalesOrder.PSNo, param);
        }

        private void PreSalesClient_GetPreSalesOrderCompleted(object sender, GetPreSalesOrderCompletedEventArgs e)
        {
            PreSalesClient.GetPreSalesOrderCompleted -= PreSalesClient_GetPreSalesOrderCompleted;
            SalesOrder.SalesOrderDetails.Clear();

            SalesOrder.CustomerName = e.Result.CustomerName;
            SalesOrder.Address = e.Result.Address;

            //Cek Apakah detailnya kosong 
            foreach (PreSalesOrderDetailDTO preSalesOrderDetail in
                e.Result.PreSalesOrderDetails)
            {
                if (preSalesOrderDetail.Inventory == null)
                    return;
            }

            if (SalesOrder.Type.ToLower() == "subgroup")
            {
                foreach (var PreSalesOrderDetailGroup in
                    e.Result.PreSalesOrderDetails.GroupBy(x => x.Inventory.Item.SubGroup.SubGroupID))
                {
                    var SODetail = new SalesOrderDetailDTO();
                    SODetail.SubGroup = new SubGroupDTO {SubGroupID = PreSalesOrderDetailGroup.Key};
                    SalesOrder.SalesOrderDetails.Add(SODetail);
                }
                GetSubGroupList(Mode.Add);
            }
            else if (SalesOrder.Type.ToLower() == "item")
            {
                foreach (var PreSalesOrderDetailGroup in
                    e.Result.PreSalesOrderDetails.GroupBy(x => x.Inventory.Item.ItemId))
                {
                    var Item = new ItemDTO();
                    foreach (PreSalesOrderDetailDTO preSalesOrderDetailDto in PreSalesOrderDetailGroup)
                    {
                        Item = preSalesOrderDetailDto.Inventory.Item;
                        break;
                    }
                    var SODetail = new SalesOrderDetailDTO();
                    SODetail.Items = new ObservableCollection<ItemDTO>();
                    SODetail.Item = Item;
                    SODetail.Items.Add(Item);
                    SODetail.Item = SODetail.Items.FirstOrDefault(s => s.ItemId == PreSalesOrderDetailGroup.Key);
                    SalesOrder.SalesOrderDetails.Add(SODetail);
                }
            }
            else
            {
                foreach (PreSalesOrderDetailDTO PreSalesOrderDetail in
                    e.Result.PreSalesOrderDetails)
                {
                    var SODetail = new SalesOrderDetailDTO();
                    SODetail.Inventory =
                        PreSalesOrderDetail.Inventory;
                    SODetail.Panjang = PreSalesOrderDetail.Panjang;
                    SODetail.Lebar = PreSalesOrderDetail.Lebar;
                    SODetail.Tinggi = PreSalesOrderDetail.Tinggi;
                    GetQtyUnit(SODetail);
                    SalesOrder.SalesOrderDetails.Add(SODetail);
                }
            }
        }

        public void GetQtyUnit(SalesOrderDetailDTO param)
        {
            if (param == null) return;
            SalesOrderDetailDTO SalesOrderDetail = param;
            if (SalesOrderDetail.Inventory.SatuanUnit != null)
                SalesOrderDetail.Qty = SalesOrderDetail.Inventory.QtyPack*
                                       (SalesOrderDetail.Panjang*
                                        SalesOrderDetail.Lebar*
                                        SalesOrderDetail.Tinggi)/
                                       SalesOrderDetail.Inventory.SatuanUnit.Pengali;

            SalesOrderDetail.Qty = SalesOrderDetail.Inventory.Item.IsRounded
                                       ? SalesOrderDetail.Qty.Round(2, MidpointRounding.AwayFromZero)
                                       : SalesOrderDetail.Qty.Round(4, MidpointRounding.AwayFromZero);

        }


        public void GetSubGroupList(Mode mode)
        {
            SubgroupClient.GetAllSubGroupCompleted += SubgroupClient_GetAllSubGroupCompleted;
            SubgroupClient.GetAllSubGroupAsync(mode);
        }

        private void SubgroupClient_GetAllSubGroupCompleted(object sender, GetAllSubGroupCompletedEventArgs e)
        {
            SubgroupClient.GetAllSubGroupCompleted -= SubgroupClient_GetAllSubGroupCompleted;
            var Subgroups = new ObservableCollection<SubGroupDTO>((from s in e.Result
                                                                   select
                                                                       new SubGroupDTO
                                                                           {
                                                                               SubGroupID = s.SubGroupID,
                                                                               SubGroupName = s.SubGroupName
                                                                           }));
            if (((Mode) e.UserState) == Mode.Edit || ((Mode) e.UserState) == Mode.Add)
                foreach (SalesOrderDetailDTO orderDetail in SalesOrder.SalesOrderDetails)
                {
                    if (orderDetail.SubGroup != null)
                    {
                        orderDetail.Subgroups = Subgroups;
                        orderDetail.SubGroup =
                            Subgroups.FirstOrDefault(s => s.SubGroupID == orderDetail.SubGroup.SubGroupID);
                    }
                }
        }

        public void GetItemList(Mode mode)
        {
            if (mode == Mode.Edit || mode == Mode.Add)
                foreach (SalesOrderDetailDTO orderDetail in SalesOrder.SalesOrderDetails)
                {
                    if (orderDetail.Item != null)
                    {
                        orderDetail.Items = new ObservableCollection<ItemDTO>();
                        orderDetail.Items.Add(orderDetail.Item);
                        orderDetail.Item =
                            orderDetail.Items.FirstOrDefault(s => s.ItemId == orderDetail.Item.ItemId);
                    }
                }
            EventAggregator.PublishMessage("Refresh", this);
        }


        public bool CanSubgroupCommand(Object param)
        {
            return true;
        }

        public bool CanItemCommand(Object param)
        {
            return true;
        }

        public bool CanInventoryCommand(Object param)
        {
            return true;
        }

        public void EntrySubGroup(Object param)
        {
            if (SalesOrder.SalesOrderDetails[0].Inventory != null && !string.IsNullOrEmpty(SalesOrder.SalesOrderDetails[0].Inventory.SerialNumber))
                return;
            if (SalesOrder.SalesOrderDetails[0].Item != null && !string.IsNullOrEmpty(SalesOrder.SalesOrderDetails[0].Item.ItemName))
                return;
            if (SalesOrder.SalesOrderDetails[0].SubGroup == null)
                SalesOrder.SalesOrderDetails[0].SubGroup = new SubGroupDTO();

            ((SalesOrderDTO) param).Type = "SubGroup";
            GridSubgroupVisibility = Visibility.Visible;
            GridItemVisibility = Visibility.Collapsed;
            GridInventoryVisibility = Visibility.Collapsed;
        }

        public void EntryItem(Object param)
        {
            if (SalesOrder.SalesOrderDetails[0].Inventory != null && !string.IsNullOrEmpty(SalesOrder.SalesOrderDetails[0].Inventory.SerialNumber))
                return;
            if (SalesOrder.SalesOrderDetails[0].SubGroup != null && !string.IsNullOrEmpty(SalesOrder.SalesOrderDetails[0].SubGroup.SubGroupName))
                return;
            if (SalesOrder.SalesOrderDetails[0].Item == null)
                SalesOrder.SalesOrderDetails[0].Item = new ItemDTO();
            ((SalesOrderDTO)param).Type = "Item";
            GridItemVisibility = Visibility.Visible;
            GridSubgroupVisibility = Visibility.Collapsed;
            GridInventoryVisibility = Visibility.Collapsed;
        }

        public void EntryInventory(Object param)
        {
            if (SalesOrder.SalesOrderDetails[0].Item != null && ! string.IsNullOrEmpty(SalesOrder.SalesOrderDetails[0].Item.ItemName))
                return;
            if (SalesOrder.SalesOrderDetails[0].SubGroup != null && !string.IsNullOrEmpty(SalesOrder.SalesOrderDetails[0].SubGroup.SubGroupName))
                return;
            if (SalesOrder.SalesOrderDetails[0].Inventory ==null)
                SalesOrder.SalesOrderDetails[0].Inventory = new InventoryDTO();

            ((SalesOrderDTO) param).Type = "Inventory";
            GridInventoryVisibility = Visibility.Visible;
            GridSubgroupVisibility = Visibility.Collapsed;
            GridItemVisibility = Visibility.Collapsed;
        }

        public void GetSubgroupByName(Object param)
        {
            if (param.GetType() == typeof (SalesOrderDetailDTO))
            {
                SalesOrderDetailCurrent = (SalesOrderDetailDTO) param;
                SubgroupClient.GetSubGroupListByNameCompleted += SubgroupClient_GetSubGroupListByNameCompleted;
                SubgroupClient.GetSubGroupListByNameAsync(SalesOrderDetailCurrent.SubGroup.SubGroupName);
            }
            else
            {
                SubgroupClient.GetSubGroupListByNameCompleted += SubgroupClient2_GetSubGroupListByNameCompleted;
                SubgroupClient.GetSubGroupListByNameAsync(param.ToString());
            }
        }

        private void SubgroupClient_GetSubGroupListByNameCompleted(object sender,
                                                                   GetSubGroupListByNameCompletedEventArgs e)
        {
            SubgroupClient.GetSubGroupListByNameCompleted -= SubgroupClient_GetSubGroupListByNameCompleted;
            Subgroups = e.Result;
        }

        public void GetItemByName(Object param)
        {
            if (param.GetType() == typeof (SalesOrderDetailDTO))
            {
                SalesOrderDetailCurrent = (SalesOrderDetailDTO) param;
                ItemClient.GetItemByNameCompleted += ItemClient_GetItemByNameCompleted;
                ItemClient.GetItemByNameAsync(SalesOrderDetailCurrent.Item.ItemName);
            }
            else
            {
                ItemClient.GetItemByNameCompleted += ItemClient_GetItemByNameCompleted;
                ItemClient.GetItemByNameAsync(param.ToString());
            }
        }

        private void ItemClient_GetItemByNameCompleted(object sender, GetItemByNameCompletedEventArgs e)
        {
            ItemClient.GetItemByNameCompleted -= ItemClient_GetItemByNameCompleted;
            Items = e.Result;
        }

        private void SubgroupClient2_GetSubGroupListByNameCompleted(object sender,
                                                                    GetSubGroupListByNameCompletedEventArgs e)
        {
            SubgroupClient.GetSubGroupListByNameCompleted -= SubgroupClient2_GetSubGroupListByNameCompleted;
            Subgroups = e.Result;
        }

        public void Print(Object param)
        {
            Navigation.MyNavigation.Navigate(new Uri("/SalesOrder/PrintPreviewSO", UriKind.Relative));
            Navigation.Args = param;
        }

        public void SendEmail(Object param)
        {
            ChooseDestination chooseDestination = new ChooseDestination();
            chooseDestination.Show();
            EventAggregator.RegisterMessage("SendDestination", (x) =>
            {
                IsBusy = true;
                client.SendEmailCompleted += client_SendEmailCompleted;
                client.SendEmailAsync(param as SalesOrderDTO, (x as WarehouseDTO).EmailFolder);
            });
        }

        private void client_SendEmailCompleted(object sender,SalesOrderServices.SendEmailCompletedEventArgs e)
        {
            IsBusy = false;
            client.SendEmailCompleted -= client_SendEmailCompleted;
            if (e.Result) MessageBox.Show("Pengiriman Selesai");
        }
    }


    public class SalesOrderWrapViewModel : ViewModelBase
    {
        private readonly InventoryServiceClient InventoryClient;
        private readonly SalesOrderServicesClient client;
        private ItemServicesClient ItemClient;
        private SubGroupServiceClient SubGroupClient;
        private List<string> _DiscTypes;
        private SalesOrderDetailDTO _SalesOrderDetail;
        private ObservableCollection<SubGroupDTO> _SubGroups;

        public SalesOrderWrapViewModel()
        {
            if (!DesignerProperties.IsInDesignTool)
            {
                EditCommand = new DelegateCommand(Edit, CanEditCommand);
                DeleteCommand = new DelegateCommand(Delete, CanDeleteCommand);

                client = new SalesOrderServicesClient();
                InventoryClient = new InventoryServiceClient();
                ItemClient = new ItemServicesClient();
                SubGroupClient = new SubGroupServiceClient();


                AddDetailCommand = new DelegateCommand(AddSalesOrderDetail, CanAddDetailCommand);
                DeleteDetailCommand = new DelegateCommand(DeleteSalesOrderDetail, CanDeleteDetailCommand);
                GetTotalDetailCommand = new DelegateCommand(GetTotalDetail, CanGetTotalDetailCommand);
                GetPpnCommand = new DelegateCommand(GetPpn, CanGetPpnCommand);
                GetTotalDiscountCommand = new DelegateCommand(GetTotalDiscount, CanGetTotalDiscount);
                GetInventoryCommand = new DelegateCommand(GetInventory, CanGetInventoryCommand);
                GetQtyUnitCommand = new DelegateCommand(GetQtyUnit, CanGetQtyUnit);

                DiscTypes = new List<string>();
                DiscTypes.Add("%");
                DiscTypes.Add("val");

                if (SalesOrderViewModel.mode == Mode.Add || SalesOrderViewModel.mode == Mode.Edit)
                {
                }
            }
        }

        public SalesOrderViewModel SalesOrderViewModel { get; set; }

        public ICommand EditCommand { get; set; }
        public ICommand DeleteCommand { get; set; }
        public ICommand AddDetailCommand { get; set; }
        public ICommand DeleteDetailCommand { get; set; }
        public ICommand SearchItemCommand { get; set; }
        public ICommand GetInventoryCommand { get; set; }
        public ICommand GetQtyUnitCommand { get; set; }
        public ICommand GetTotalDetailCommand { get; set; }
        public ICommand GetPpnCommand { get; set; }
        public ICommand GetTotalDiscountCommand { get; set; }

        public SalesOrderDetailDTO SalesOrderDetail
        {
            get { return _SalesOrderDetail; }
            private set
            {
                if (SalesOrderDetail == value) return;
                _SalesOrderDetail = value;
                FirePropertyChanged("SalesOrderDetail");
            }
        }

        public List<string> DiscTypes
        {
            get { return _DiscTypes; }
            private set
            {
                if (DiscTypes == value) return;
                _DiscTypes = value;
                FirePropertyChanged("DiscTypes");
            }
        }

        public bool CanEditCommand(Object param)
        {
            return true;
        }

        public bool CanDeleteCommand(Object param)
        {
            return true;
        }

        public bool CanAddDetailCommand(Object param)
        {
            return true;
        }

        public bool CanDeleteDetailCommand(Object param)
        {
            return true;
        }

        public bool CanGetInventoryCommand(Object param)
        {
            return true;
        }

        public bool CanGetQtyUnit(Object param)
        {
            return true;
        }

        public bool CanGetTotalDetailCommand(Object param)
        {
            return true;
        }

        public bool CanGetPpnCommand(Object param)
        {
            return true;
        }

        private bool CanSearchItemCommand(Object param)
        {
            return true;
        }


        public void Edit(Object param)
        {
            SalesOrderViewModel.mode = Mode.Edit;
            Navigation.MyNavigation.Navigate(new Uri("/SalesOrder/frmAdd", UriKind.Relative));
            Navigation.Args = param;
        }

        public void Delete(Object param)
        {          
            DeleteConfirmation deleteConfirmation = new DeleteConfirmation();
            deleteConfirmation.Show();
            EventAggregator.RegisterMessage("ApprovalSucceeded", (x) =>
            {
                deleteConfirmation.Close();
                client.DeleteCompleted += client_DeleteCompleted;
                client.DeleteAsync((SalesOrderDTO)param);
            });

        }

        private void client_DeleteCompleted(object sender, AsyncCompletedEventArgs e)
        {
            client.DeleteCompleted -= client_DeleteCompleted;
            MessageBox.Show("Delete Success!");
            SalesOrderViewModel.mode = Mode.Idle;
            var VM = new SalesOrderViewModel();
        }


        public void AddSalesOrderDetail(Object param)
        {
            //SalesOrderDetail.SubGroup = new SubGroupDTO();
            //SalesOrderDetail.Subgroups = SalesOrderViewModel.SalesOrder.SalesOrderDetails[0].Subgroups;
            SalesOrderDetail = new SalesOrderDetailDTO();
            var countSO = SalesOrderViewModel.SalesOrder.SalesOrderDetails.Count;
            if (countSO >= 1)
                if (SalesOrderViewModel.SalesOrder.SalesOrderDetails[countSO - 1].Price > 0)
                {
                    SalesOrderDetail.Price = SalesOrderViewModel.SalesOrder.SalesOrderDetails[countSO - 1].Price;
                    SalesOrderDetail.DiscountType = SalesOrderViewModel.SalesOrder.SalesOrderDetails[countSO - 1].DiscountType;
                    SalesOrderDetail.Discount = SalesOrderViewModel.SalesOrder.SalesOrderDetails[countSO - 1].Discount;
                }
                    

            if (SalesOrderViewModel.SalesOrder.Type == "Inventory")
            {
                SalesOrderDetail.Inventory = new InventoryDTO();
                SalesOrderViewModel.SalesOrder.SalesOrderDetails.Add(SalesOrderDetail);
            }
            else if (SalesOrderViewModel.SalesOrder.Type == "Item")
            {
                SalesOrderDetail.Item = new ItemDTO();
                SalesOrderViewModel.SalesOrder.SalesOrderDetails.Add(SalesOrderDetail);
                EventAggregator.PublishMessage("SetFocusFirstColumnItem", this);
            }
            else
            {
                SalesOrderDetail.SubGroup = new SubGroupDTO();
                SalesOrderViewModel.SalesOrder.SalesOrderDetails.Add(SalesOrderDetail);
                EventAggregator.PublishMessage("SetFocusFirstColumnSubgroup", this);
            }
        }

        public void DeleteSalesOrderDetail(Object param)
        {
            var SalesOrderDetail = (SalesOrderDetailDTO) param;
            if (SalesOrderViewModel.SalesOrder.SalesOrderDetails.Count > 1)
            {
                //Jika paramnya null hapus yg terakhir
                if (SalesOrderDetail == null)
                {
                    SalesOrderViewModel.SalesOrder.SalesOrderDetails.RemoveAt(
                        SalesOrderViewModel.SalesOrder.SalesOrderDetails.Count - 1);
                    return;
                }
                SalesOrderViewModel.SalesOrder.SalesOrderDetails.Remove(SalesOrderDetail);
                GetTotalDetail(null);
            }
        }

        public void GetTotalDetail(Object param)
        {
            Decimal Qty = 0;

            if(param != null)
            {
                SalesOrderDetail = (SalesOrderDetailDTO)param;
                switch (SalesOrderViewModel.SalesOrder.Type)
                {
                    case "Inventory":
                        if (SalesOrderDetail.Inventory != null) Qty = SalesOrderDetail.Qty;
                        break;
                    default:
                        Qty = SalesOrderDetail.Qty;
                        break;
                }
                SalesOrderDetail.TotalDetail = SalesOrderDetail.DiscountType != "%"
                                                   ? (Qty * SalesOrderDetail.Price) - SalesOrderDetail.Discount
                                                   : Qty *
                                                     (SalesOrderDetail.Price -
                                                      ((SalesOrderDetail.Price) * SalesOrderDetail.Discount / 100));
            }
            
            if (SalesOrderViewModel != null)
            {
                SalesOrderViewModel.SalesOrder.SubTotal =
                    SalesOrderViewModel.SalesOrder.SalesOrderDetails.Sum(p => p.TotalDetail);
                if (SalesOrderViewModel.SalesOrder.DiscountType != "%")
                    SalesOrderViewModel.SalesOrder.AfterDiscount = SalesOrderViewModel.SalesOrder.SubTotal -
                                                                   SalesOrderViewModel.SalesOrder.Discount;
                else
                    SalesOrderViewModel.SalesOrder.AfterDiscount = SalesOrderViewModel.SalesOrder.SubTotal -
                                                                   (SalesOrderViewModel.SalesOrder.SubTotal*
                                                                    SalesOrderViewModel.SalesOrder.Discount/100);
                if (SalesOrderViewModel.SalesOrder.IsPpn)
                    SalesOrderViewModel.SalesOrder.Ppn = SalesOrderViewModel.SalesOrder.AfterDiscount*10/100;
                if (SalesOrderViewModel.SalesOrder.Ppn > 0)
                    SalesOrderViewModel.SalesOrder.IsPpn = true;
                SalesOrderViewModel.SalesOrder.Total =
                    SalesOrderViewModel.SalesOrder.AfterDiscount + SalesOrderViewModel.SalesOrder.Ppn;
            }
        }

        public void GetPpn(Object param)
        {
            var SalesOrder = (SalesOrderDTO) param;
            if (SalesOrder.IsPpn)
            {
                SalesOrder.Ppn = SalesOrder.AfterDiscount*10/100;
                SalesOrder.Total = SalesOrder.AfterDiscount + SalesOrder.Ppn;
            }
            else
            {
                SalesOrder.Ppn = 0;
                SalesOrder.Total = SalesOrder.AfterDiscount + SalesOrder.Ppn;
            }
        }

        public bool CanGetTotalDiscount(Object param)
        {
            return true;
        }

        public void GetTotalDiscount(Object param)
        {
            var SalesOrder = (SalesOrderDTO) param;
            if (SalesOrder.SalesOrderDetails != null)
                SalesOrder.SubTotal =
                    SalesOrder.SalesOrderDetails.Sum(p => p.TotalDetail);
            if (SalesOrder.DiscountType != "%")
                SalesOrder.AfterDiscount = SalesOrder.SubTotal - SalesOrder.Discount;
            else
                SalesOrder.AfterDiscount = SalesOrder.SubTotal - (SalesOrder.SubTotal*SalesOrder.Discount/100);
            if (SalesOrder.IsPpn)
                SalesOrder.Ppn = SalesOrder.AfterDiscount*10/100;
            if (SalesOrder.Ppn > 0)
                SalesOrder.IsPpn = true;
            SalesOrder.Total =
                SalesOrder.AfterDiscount + SalesOrder.Ppn;
        }


        public void GetInventory(Object param)
        {
            SalesOrderDetail = (SalesOrderDetailDTO) param;
            //if (SalesOrderDetail.Inventory == null) SalesOrderDetail.Inventory = new InventoryDTO();
            string SerialNumber = SalesOrderDetail.Inventory.SerialNumber;
            //if (SalesOrderViewModel.SalesOrder.SalesOrderDetails.Count >1 && SalesOrderViewModel.SalesOrder.SalesOrderDetails.Any(x => x.Inventory.SerialNumber == SerialNumber)) return;
            //;
            InventoryClient.GetInventoryCompleted +=
                InventoryClient_GetInventoryCompleted;
            InventoryClient.GetInventoryAsync(SerialNumber);
        }

        private void InventoryClient_GetInventoryCompleted(object sender, GetInventoryCompletedEventArgs e)
        {
            InventoryClient.GetInventoryCompleted -=
                InventoryClient_GetInventoryCompleted;
            InventoryDTO InventoryTemp = e.Result;

            if (string.IsNullOrEmpty(InventoryTemp.SerialNumber))
                MessageBox.Show("Barang tidak ditemukan, coba entry secara manual");

            if (null != InventoryTemp && ! string.IsNullOrEmpty(InventoryTemp.SerialNumber))
            {
                SalesOrderDetail.Inventory = InventoryTemp;
                SalesOrderDetail.Panjang = InventoryTemp.Panjang;
                SalesOrderDetail.Lebar = InventoryTemp.Lebar;
                if (InventoryTemp.Warehouses.Count > 0)
                    SalesOrderDetail.Qty = InventoryTemp.Warehouses.FirstOrDefault().Qty;
                SalesOrderDetail.Panjang = InventoryTemp.Panjang;
                SalesOrderDetail.Lebar = InventoryTemp.Lebar;
                if (InventoryTemp.Warehouses.Count > 0)
                    SalesOrderDetail.Tinggi = InventoryTemp.Warehouses.FirstOrDefault().Sheet;
                SalesOrderDetail.Inventory.Item =
                    e.Result.Item;
                SalesOrderDetail.Inventory.SatuanUnit =
                    e.Result.SatuanUnit;
            }else
            {
               MessageBox.Show("Barang tidak ditemukan, coba entry secara manual");
            }
        }

        public void GetQtyUnit(Object param)
        {
            if (param == null) return;
            SalesOrderDetail = param as SalesOrderDetailDTO;
            if (SalesOrderDetail.Inventory != null)
                if (SalesOrderDetail.Inventory.SatuanUnit != null)
                {
                    SalesOrderDetail.Qty = SalesOrderDetail.Inventory.QtyPack *
                                          (SalesOrderDetail.Panjang *
                                           SalesOrderDetail.Lebar *
                                           SalesOrderDetail.Tinggi) /
                                          SalesOrderDetail.Inventory.SatuanUnit.Pengali;

                    SalesOrderDetail.Qty = SalesOrderDetail.Inventory.Item.IsRounded
                                               ? SalesOrderDetail.Qty.Round(2, MidpointRounding.AwayFromZero)
                                               : SalesOrderDetail.Qty.Round(4, MidpointRounding.AwayFromZero);


                }
                   
            GetTotalDetail(SalesOrderDetail);
        }
    }


    public class SalesOrderConverter : IValueConverter
    {
        #region IValueConverter Members

        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value != null)
            {
                return ((dynamic) value).SONo;
            }
            else
            {
                return string.Empty;
            }
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }

        #endregion
    }
}